// auth.service.ts
import {
  Injectable,
  UnauthorizedException,
  Logger,
  ConflictException,
} from '@nestjs/common';
import * as bcrypt from 'bcryptjs';
import { JwtService } from '@nestjs/jwt';
import { UserService } from '../users/users.service';
import { User } from '../users/users.entity';

@Injectable()
export class AuthService {
  private readonly logger = new Logger(AuthService.name);

  constructor(
    private readonly userService: UserService,
    private readonly jwtService: JwtService,
  ) {}

  // 用户登录时，验证手机号和密码
  async validateUser(
    phone: string,
    password: string,
  ): Promise<Omit<User, 'password'>> {
    // 清理手机号，去除空格等不可见字符
    const cleanPhone = phone.trim();
    this.logger.log(`验证用户，手机号: ${cleanPhone}`);
    const user = await this.userService.findByPhone(cleanPhone);
    if (!user) {
      this.logger.log(`用户未找到，手机号: ${cleanPhone}`);
      throw new UnauthorizedException('手机号或密码错误');
    }

    // 验证用户是否有密码（第三方登录用户可能没有）
    if (!user.password) {
      this.logger.log(`用户没有设置密码，手机号: ${cleanPhone}`);
      throw new UnauthorizedException('请使用第三方登录方式');
    }

    this.logger.log(`前端输入密码长度: ${password.length}`);
    this.logger.log(`数据库密码长度: ${user.password.length}`);
    
    // 使用 timing-safe 的密码比较防止时序攻击
    const isMatch = await bcrypt.compare(password, user.password);
    this.logger.log(`密码比对结果: ${isMatch}`);

    if (!isMatch) {
      throw new UnauthorizedException('手机号或密码错误');
    }

    const { password: _, ...result } = user; // 过滤掉密码字段
    return result;
  }

  // 登录并生成 JWT
  async login(user: any) {
    this.logger.log(`用户登录，手机号: ${user.phone}`);
    // 注意：这里传入的user对象应包含phone和password字段
    const validatedUser = await this.validateUser(user.phone, user.password);

    // 确保用户对象包含ID（数字类型）
    const payload = { phone: validatedUser.phone, id: validatedUser.id };
    this.logger.log(`生成JWT token，用户ID: ${validatedUser.id}，负载: ${JSON.stringify(payload)}`);
    return {
      access_token: this.jwtService.sign(payload),
      user: validatedUser,
    };
  }

  // 注册用户
  async register(userData: { phone: string; password: string; name: string }) {
    this.logger.log(`注册用户，手机号: ${userData.phone}`);
    // 清理手机号，去除空格等不可见字符
    const cleanPhone = userData.phone.trim();
    const existingUser = await this.userService.findByPhone(cleanPhone);
    if (existingUser) {
      this.logger.log(`用户已存在，手机号: ${cleanPhone}`);
      throw new ConflictException('用户已存在');
    }

    // 密码强度验证
    if (userData.password.length < 6) {
      throw new ConflictException('密码长度至少为6位');
    }

    const hashedPassword = await bcrypt.hash(userData.password, 10);
    this.logger.log(`密码加密完成，手机号: ${cleanPhone}`);
    const newUser = await this.userService.createUser(
      cleanPhone,
      hashedPassword,
      userData.name,
    );

    // 注册成功后自动生成JWT token
    const payload = { phone: newUser.phone, id: newUser.id };
    this.logger.log(`注册成功，生成JWT token，用户ID: ${newUser.id}，负载: ${JSON.stringify(payload)}`);
    return {
      access_token: this.jwtService.sign(payload),
      user: newUser,
    };
  }

  // Google登录
  async googleLogin(googleUser: any) {
    this.logger.log(`Google用户登录，邮箱: ${googleUser.email}`);

    // 查找用户是否已存在
    let user = await this.userService.findByEmail(googleUser.email);

    // 如果用户不存在，则创建新用户
    if (!user) {
      const createdUser = await this.userService.createGoogleUser({
        email: googleUser.email,
        name: `${googleUser.firstName} ${googleUser.lastName}`,
        googleId: googleUser.googleId,
        avatar: googleUser.picture,
        password: this.generateRandomPassword(),
      });
      user = createdUser as any as User;
    } else {
      // 如果用户存在，更新其Google ID和头像
      await this.userService.updateUserGoogleInfo(user.id, {
        googleId: googleUser.googleId,
        avatar: googleUser.picture,
      });
    }

    // 确保用户存在再继续
    if (!user) {
      throw new UnauthorizedException('无法创建或查找用户');
    }

    // 生成JWT token
    const payload = { email: user.email, id: user.id };
    return {
      access_token: this.jwtService.sign(payload),
      user: user,
    };
  }

  // Facebook登录
  async facebookLogin(facebookUser: any) {
    this.logger.log(`Facebook用户登录，用户ID: ${facebookUser.facebookId}`);

    // 查找用户是否已存在
    let user = await this.userService.findByFacebookId(facebookUser.facebookId);

    // 如果用户不存在，则创建新用户
    if (!user) {
      const createdUser = await this.userService.createFacebookUser({
        facebookId: facebookUser.facebookId,
        email: facebookUser.email,
        name: `${facebookUser.firstName} ${facebookUser.lastName}`,
        avatar: facebookUser.picture,
        password: this.generateRandomPassword(),
      });
      user = createdUser as any as User;
    }

    // 确保用户存在再继续
    if (!user) {
      throw new UnauthorizedException('无法创建或查找用户');
    }

    // 生成JWT token
    const payload: { id: number; email?: string; phone?: string } = {
      id: user.id,
    };
    if (user.email) {
      payload['email'] = user.email;
    } else if (user.phone) {
      payload['phone'] = user.phone;
    }

    return {
      access_token: this.jwtService.sign(payload),
      user: user,
    };
  }

  // WeChat登录
  async wechatLogin(wechatUser: any) {
    this.logger.log(`WeChat用户登录，用户ID: ${wechatUser.wechatId}`);

    // 查找用户是否已存在
    let user = await this.userService.findByWechatId(wechatUser.wechatId);

    // 如果用户不存在，则创建新用户
    if (!user) {
      const createdUser = await this.userService.createWechatUser({
        wechatId: wechatUser.wechatId,
        name: wechatUser.nickname,
        gender: wechatUser.gender,
        avatar: wechatUser.avatar,
        password: this.generateRandomPassword(),
      });
      user = createdUser as any as User;
    }

    // 确保用户存在再继续
    if (!user) {
      throw new UnauthorizedException('无法创建或查找用户');
    }

    // 生成JWT token
    const payload: { id: number; phone?: string } = {
      id: user.id,
    };
    if (user.phone) {
      payload['phone'] = user.phone;
    }

    return {
      access_token: this.jwtService.sign(payload),
      user: user,
    };
  }

  // 生成随机密码的辅助方法
  private generateRandomPassword(): string {
    return Math.random().toString(36).slice(-8);
  }
}